package com.tsunami.provider;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class TodoListProvider extends ContentProvider {
	
	 private static final String TAG = "TodoListProvider";
	 private static final String DATABASE_NAME = "todo_list.db";
	 private static final int DATABASE_VERSION = 1;
	 
	 private static HashMap<String, String> listProjectionMap;
	 private static HashMap<String, String> taskProjectionMap;
	 
	 private static final int LIST = 1;
	 private static final int LIST_ID = 2;
	 private static final int TASK = 3;
	 private static final int TASK_ID = 4;
	 
	 private static final UriMatcher uriMatcher;

	 private DatabaseHelper databaseHelper;
	 
	 static {
		 
		 uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		 uriMatcher.addURI(TodoList.AUTHORITY, "list", LIST);
		 uriMatcher.addURI(TodoList.AUTHORITY, "list/#", LIST_ID);
		 uriMatcher.addURI(TodoList.AUTHORITY, "task", TASK);
		 uriMatcher.addURI(TodoList.AUTHORITY, "task/#", TASK_ID);

	     listProjectionMap = new HashMap<String, String>();
	     listProjectionMap.put(TodoList.List._ID, TodoList.List._ID);
	     listProjectionMap.put(TodoList.List.COLUMN_NAME_TITLE, TodoList.List.COLUMN_NAME_TITLE);
	     listProjectionMap.put(TodoList.List.COLUMN_NAME_CREATED_DATE, TodoList.List.COLUMN_NAME_CREATED_DATE);
	     listProjectionMap.put(TodoList.List.COLUMN_NAME_SOURCE, TodoList.List.COLUMN_NAME_SOURCE);
	     listProjectionMap.put(TodoList.List.COLUMN_NAME_DISPLAY_ORDER, TodoList.List.COLUMN_NAME_DISPLAY_ORDER);
	     
	     taskProjectionMap = new HashMap<String, String>();
	     taskProjectionMap.put(TodoList.Task._ID, TodoList.Task._ID);
	     taskProjectionMap.put(TodoList.Task.COLUMN_NAME_LIST_ID, TodoList.Task.COLUMN_NAME_LIST_ID);
	     taskProjectionMap.put(TodoList.Task.COLUMN_NAME_DESCRIPTION, TodoList.Task.COLUMN_NAME_DESCRIPTION);
	     taskProjectionMap.put(TodoList.Task.COLUMN_NAME_CREATED_DATE, TodoList.Task.COLUMN_NAME_CREATED_DATE);
	     taskProjectionMap.put(TodoList.Task.COLUMN_NAME_NOTES, TodoList.Task.COLUMN_NAME_NOTES);
	     taskProjectionMap.put(TodoList.Task.COLUMN_NAME_DUE_DATE, TodoList.Task.COLUMN_NAME_DUE_DATE);
	     taskProjectionMap.put(TodoList.Task.COLUMN_NAME_COMPLETED_DATE, TodoList.Task.COLUMN_NAME_COMPLETED_DATE);
	     taskProjectionMap.put(TodoList.Task.COLUMN_NAME_DISPLAY_ORDER, TodoList.Task.COLUMN_NAME_DISPLAY_ORDER);
	 }

	 
	 
	static class DatabaseHelper extends SQLiteOpenHelper {

		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}


		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL("CREATE TABLE " + TodoList.List.TABLE_NAME + " ("
					+ TodoList.List._ID + " INTEGER PRIMARY KEY,"
					+ TodoList.List.COLUMN_NAME_TITLE + " TEXT,"
					+ TodoList.List.COLUMN_NAME_CREATED_DATE + " INTEGER,"
					+ TodoList.List.COLUMN_NAME_SOURCE + " INTEGER,"
					+ TodoList.List.COLUMN_NAME_DISPLAY_ORDER + " INTEGER"
					+ ");");

			db.execSQL("CREATE TABLE " + TodoList.Task.TABLE_NAME + " ("
					+ TodoList.Task._ID + " INTEGER PRIMARY KEY,"
					+ TodoList.Task.COLUMN_NAME_LIST_ID + " INTEGER,"
					+ TodoList.Task.COLUMN_NAME_DESCRIPTION + " TEXT,"
					+ TodoList.Task.COLUMN_NAME_CREATED_DATE + " INTEGER,"
					+ TodoList.Task.COLUMN_NAME_NOTES + " TEXT,"
					+ TodoList.Task.COLUMN_NAME_DUE_DATE + " INTEGER,"
					+ TodoList.Task.COLUMN_NAME_COMPLETED_DATE + " INTEGER,"
					+ TodoList.Task.COLUMN_NAME_DISPLAY_ORDER + " INTEGER,"
					+ "foreign key(" + TodoList.Task.COLUMN_NAME_LIST_ID
					+ ") references " + TodoList.List.TABLE_NAME + "("
					+ TodoList.List._ID + ")" + ");");
			ContentValues value = new ContentValues();
			value.put(TodoList.List.COLUMN_NAME_TITLE, Resources.getSystem()
					.getString(android.R.string.untitled));
			value.put(TodoList.List.COLUMN_NAME_CREATED_DATE,
					Long.valueOf(System.currentTimeMillis()));
			value.put(TodoList.List.COLUMN_NAME_SOURCE,
					TodoList.List.SOURCE_USER);
			db.insert(TodoList.List.TABLE_NAME, null, value);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");

			db.execSQL("DROP TABLE IF EXISTS " + TodoList.List.TABLE_NAME);
			db.execSQL("; DROP TABLE IF EXISTS " + TodoList.Task.TABLE_NAME);

			onCreate(db);
		}
	}

	@Override
	public int delete(Uri _uri, String _where, String[] _whereArgs) {
		
        SQLiteDatabase db = databaseHelper.getWritableDatabase();
        String finalWhere;

        int count;
        
        switch (uriMatcher.match(_uri)) {

           
            case LIST:
                count = db.delete(
                    TodoList.List.TABLE_NAME,  
                    _where,                     
                    _whereArgs            
                );
                break;

              
            case LIST_ID:
               
                finalWhere =
                        TodoList.List._ID +                              
                        " = " +                                          
                        _uri.getPathSegments().                          
                            get(TodoList.List.LIST_ID_PATH_POSITION)
                ;

              
                if (_where != null) {
                    finalWhere = finalWhere + " AND " + _where;
                }

               
                count = db.delete(
                	TodoList.List.TABLE_NAME,  
                    finalWhere,                
                    _whereArgs                 
                );
                break;
                
            case TASK:
            	count = db.delete(
                        TodoList.Task.TABLE_NAME,  
                        _where,                     
                        _whereArgs            
                    );
            	break;
            	
            case TASK_ID:
            	 finalWhere =
                     TodoList.Task._ID +                              
                     " = " +                                          
                     _uri.getPathSegments().                          
                         get(TodoList.Task.TASK_ID_PATH_POSITION)
	             ;
	
	           
	             if (_where != null) {
	                 finalWhere = finalWhere + " AND " + _where;
	             }
	
	            
	             count = db.delete(
	             	TodoList.Task.TABLE_NAME,  
	                 finalWhere,                
	                 _whereArgs                 
	             );
            	break;

            default:
                throw new IllegalArgumentException("Unknown URI " + _uri);
        }

      
       getContext().getContentResolver().notifyChange(_uri, null);

       return count;
	}

	@Override
	public String getType(Uri _uri) {
		switch (uriMatcher.match(_uri)) {

			case LIST:
	        	return TodoList.List.CONTENT_TYPE;
	        case LIST_ID:
	        	return TodoList.List.CONTENT_ITEM_TYPE;
	        case TASK:
	        	return TodoList.Task.CONTENT_TYPE;
	        case TASK_ID:
	        	return TodoList.Task.CONTENT_ITEM_TYPE;
	        default:
	            throw new IllegalArgumentException("Unknown URI " + _uri);
		}
	}

	@Override
	public Uri insert(Uri _uri, ContentValues _values) {
		if (_values == null)
			 throw new IllegalArgumentException("ContentValues in null ");
		Long now = Long.valueOf(System.currentTimeMillis());
		SQLiteDatabase db = databaseHelper.getWritableDatabase();
		long rowId;
		switch(uriMatcher.match(_uri)) {
			case LIST:
				if (false == _values.containsKey(TodoList.List.COLUMN_NAME_TITLE))
					_values.put(TodoList.List.COLUMN_NAME_TITLE, Resources.getSystem().getString(android.R.string.untitled));
				if (false == _values.containsKey(TodoList.List.COLUMN_NAME_CREATED_DATE))
					_values.put(TodoList.List.COLUMN_NAME_CREATED_DATE, now);
				if (false == _values.containsKey(TodoList.List.COLUMN_NAME_SOURCE))
					_values.put(TodoList.List.COLUMN_NAME_SOURCE, TodoList.List.SOURCE_USER);
				

				rowId = db.insert(TodoList.List.TABLE_NAME, null, _values);

		        if (rowId > 0) {
		           
		            Uri listUri = ContentUris.withAppendedId(TodoList.List.CONTENT_ID_URI_BASE, rowId);

		            getContext().getContentResolver().notifyChange(listUri, null);
		            return listUri;
		        }
		        throw new SQLException("Failed to insert row into " + _uri);
			case TASK:
				if (false == _values.containsKey(TodoList.Task.COLUMN_NAME_LIST_ID))
					throw new IllegalArgumentException("list_id can not be null");
				if (false == _values.containsKey(TodoList.Task.COLUMN_NAME_CREATED_DATE))
					_values.put(TodoList.Task.COLUMN_NAME_CREATED_DATE, now);
				if (false == _values.containsKey(TodoList.Task.COLUMN_NAME_DISPLAY_ORDER))
					throw new IllegalArgumentException("display_order can not be null");
				

				rowId = db.insert(TodoList.Task.TABLE_NAME, null, _values);

		        if (rowId > 0) {
		           
		            Uri taskUri = ContentUris.withAppendedId(TodoList.Task.CONTENT_ID_URI_BASE, rowId);

		            getContext().getContentResolver().notifyChange(taskUri, null);
		            return taskUri;
		        }
		        throw new SQLException("Failed to insert row into " + _uri);
			default:
				 throw new IllegalArgumentException("Unknown URI " + _uri);
		}
	}

	@Override
	public boolean onCreate() {
		databaseHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public Cursor query(Uri _uri, String[] _projection, String _selection,
			String[] _selectionArgs, String _sortOrder) {
		
		 SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		 String orderBy;
		 
		 switch (uriMatcher.match(_uri)) {
        
	         case LIST:
	        	 qb.setTables(TodoList.List.TABLE_NAME);
	             qb.setProjectionMap(listProjectionMap);
	             orderBy = TextUtils.isEmpty(_sortOrder)? TodoList.List.DEFAULT_SORT_ORDER : _sortOrder;
	             break;
	
	         case LIST_ID:
	        	 qb.setTables(TodoList.List.TABLE_NAME);
	             qb.setProjectionMap(listProjectionMap);
	             qb.appendWhere(
	                 TodoList.List._ID +    
	                 "=" +	                
	                 _uri.getPathSegments().get(TodoList.List.LIST_ID_PATH_POSITION));
	             orderBy = TextUtils.isEmpty(_sortOrder)? TodoList.List.DEFAULT_SORT_ORDER : _sortOrder;
	             break;
	
	         case TASK:
	        	 qb.setTables(TodoList.Task.TABLE_NAME);
	             qb.setProjectionMap(taskProjectionMap);
	             orderBy = TextUtils.isEmpty(_sortOrder)? TodoList.Task.DEFAULT_SORT_ORDER : _sortOrder;
	             break;
	
	         case TASK_ID:
	        	 qb.setTables(TodoList.Task.TABLE_NAME);
	             qb.setProjectionMap(taskProjectionMap);
	             qb.appendWhere(
	                 TodoList.Task._ID +    
	                 "=" +	                
	                 _uri.getPathSegments().get(TodoList.Task.TASK_ID_PATH_POSITION));
	             orderBy = TextUtils.isEmpty(_sortOrder)? TodoList.Task.DEFAULT_SORT_ORDER : _sortOrder;
	             break;
	
	         default:
	             throw new IllegalArgumentException("Unknown URI " + _uri);
		 }
		 
		 SQLiteDatabase db =databaseHelper.getReadableDatabase();
		 Cursor c = qb.query(
		           db,            
		           _projection,    
		           _selection,     
		           _selectionArgs, 
		           null,         
		           null,         
		           orderBy       
		       );
		 c.setNotificationUri(getContext().getContentResolver(), _uri);
	     return c;
	}

	@Override
	public int update(Uri _uri, ContentValues _values, String _where,
			String[] _whereArgs) {
		if (_values == null)
			 throw new IllegalArgumentException("ContentValues in null ");
		
		SQLiteDatabase db = databaseHelper.getWritableDatabase();
		int count;
		String finalWhere;
		
		switch (uriMatcher.match(_uri)) {
		case LIST:
			count = db.update(TodoList.List.TABLE_NAME, _values, _where,
					_whereArgs);
			break;
		case LIST_ID:

			finalWhere = TodoList.List._ID
					+ " = "
					+ _uri.getPathSegments().get(
							TodoList.List.LIST_ID_PATH_POSITION);

			if (_where != null) {
				finalWhere = finalWhere + " AND " + _where;
			}

			count = db.update(TodoList.List.TABLE_NAME, _values, finalWhere,
					_whereArgs);
			break;
		case TASK:
			count = db.update(TodoList.Task.TABLE_NAME, _values, _where,
					_whereArgs);
			break;
		case TASK_ID:

			finalWhere = TodoList.Task._ID
					+ " = "
					+ _uri.getPathSegments().get(
							TodoList.Task.TASK_ID_PATH_POSITION);

			if (_where != null) {
				finalWhere = finalWhere + " AND " + _where;
			}

			count = db.update(TodoList.Task.TABLE_NAME, _values, finalWhere,
					_whereArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + _uri);
		}
		
		getContext().getContentResolver().notifyChange(_uri, null);
		return count;
	}

	

}
